/*/////////////////////////////////////////////////////////////////////////////////
/// An
///    ___   ____ ___ _____ ___  ____
///   / _ \ / ___|_ _|_   _/ _ \|  _ \
///  | | | | |  _ | |  | || | | | |_) |
///  | |_| | |_| || |  | || |_| |  _ <
///   \___/ \____|___| |_| \___/|_| \_\
///                              File
///
/// Copyright (c) 2008-2009 Ismail TARIM <ismail@royalspor.com> and the Ogitor Team
//
//This program is free software; you can redistribute it and/or modify it under
//the terms of the GNU Lesser General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT
//ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
//FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License along with
//this program; if not, write to the Free Software Foundation, Inc., 59 Temple
//Place - Suite 330, Boston, MA 02111-1307, USA, or go to
//http://www.gnu.org/copyleft/lesser.txt.
////////////////////////////////////////////////////////////////////////////////*/

#pragma once

namespace Ogitors
{
    class LightVisualHelper;

    //! Light editor class
    /*!  
        Light editor class that assists in editing Light(s)
    */
    class OgitorExport CLightEditor: public CBaseEditor
    {
        friend class CLightEditorFactory;
    public:
        static OgitorsPropertyDefMap propertyDefs;

        /// Returns the Factory associated with this object
        static CBaseEditorFactory *getFactory();
        /// Returns the Factory associated with this object can be overridden
        virtual CBaseEditorFactory *getFactoryDynamic();
        /**
        * Sets light position
        * @param position light position
        * @param display flag signifying whether or not to update light position field in treeview
        */
        void              setPosition(const Ogre::Vector3& position, bool display);
        /**
        * Fetches light position
        * @return light position
        */
        Ogre::Vector3     getPosition();
        /**
        * Sets light position
        * @param orientation light orientation
        * @param display flag signifying whether or not to update light orientation field in treeview
        */
        void              setOrientation(const Ogre::Quaternion& orientation, bool display);
        /**
        * Fetches light orientation
        * @return light orientation
        */
        Ogre::Quaternion  getOrientation();
        /**
        * Sets light direction
        * @param value light direction
        * @param display flag signifying whether or not to update light direction field in treeview
        */
        void              setDirection(const Ogre::Vector3& value, bool display);
        /**
        * Fetches light direction
        * @return light direction
        */
        Ogre::Vector3     getDirection();
        /**
        * Sets light type (@see Ogre::Light::LightTypes)
        * @param value light type
        * @param display flag signifying whether or not to update light type field in treeview
        */
        void              setLightType(const int& value, bool display);
        /**
        * Fetches light type (@see Ogre::Light::LightTypes)
        * @return light type
        */
        int               getLightType();
        /**
        * Sets light diffuse color
        * @param value light diffuse color
        * @param display flag signifying whether or not to update light diffuse color field in treeview
        */
        void              setDiffuse(const Ogre::ColourValue& value, bool display);
        /**
        * Fetches light diffuse color
        * @return light diffuse color
        */
        Ogre::ColourValue getDiffuse();
        /**
        * Sets light specular color
        * @param value light specular color
        * @param display flag signifying whether or not to update light specular color field in treeview
        */
        void              setSpecular(const Ogre::ColourValue& value, bool display);
        /**
        * Fetches light specular color
        * @return light specular color
        */
        Ogre::ColourValue getSpecular();
        /**
        * Sets light range
        * @param value light range
        * @param display flag signifying whether or not to update light range field in treeview
        */
        void              setRange(const Ogre::Vector3& value, bool display);
        /**
        * Fetches light light
        * @return light light
        */
        Ogre::Vector3     getRange();
        /**
        * Sets light attenuation range
        * @param value light attenuation range
        * @param display flag signifying whether or not to update light attenuation range field in treeview
        */
        void              setAttenuation(const Ogre::Vector4& value, bool display);
        /**
        * Fetches light attenuation range
        * @return light attenuation range
        */
        Ogre::Vector4     getAttenuation();
        /**
        * Sets light power (intensity)
        * @param value light power
        * @param display flag signifying whether or not to update light power field in treeview
        */
        void              setPower(const Ogre::Real& value, bool display);
        /**
        * Fetches light power (intensity)
        * @return light power
        */
        Ogre::Real        getPower();
        /**
        * Sets casting shadows flag; if true, light will be casting shadows
        * @param value casting shadows flag
        * @param display flag signifying whether or not to update casting shadows field in treeview
        */
        void              setCastShadows(const bool& value, bool display);
        /**
        * Fetches casting shadows flag
        * @return casting shadows flag
        */
        bool              getCastShadows();

        /** @copydoc CBaseEditor::attach(CBaseEditor *) */
        virtual void     attach(CBaseEditor *parent);
        /** @copydoc CBaseEditor::detach() */
        virtual void     detach();
        /** @copydoc CBaseEditor::load() */
        virtual bool load();
        /** @copydoc CBaseEditor::unLoad() */
        virtual bool unLoad();
        /** @copydoc CBaseEditor::handleCustomFunction(int, Ogre::String) */
        virtual bool     handleCustomFunction(int BIND_ID, Ogre::String val);
        /** @copydoc CBaseEditor::processParameters(Ogre::NameValuePairList &) */
        virtual void     processParameters(Ogre::NameValuePairList &params);
        /** @copydoc CBaseEditor::getObjectProperties(Ogre::NameValuePairList &) */
        virtual void     getObjectProperties(Ogre::NameValuePairList &retList);
        /** @copydoc CBaseEditor::setupPropertiesWnd(bool) */
        virtual bool     setupPropertiesWnd(bool present);
        /// Overridden by Editor Objects to Import Object Dependant Properties
        /** @copydoc CBaseEditor::getHandle() */
        inline virtual void *getHandle() {return static_cast<void*>(m_Handle);};
        /** @copydoc CBaseEditor::restore(Ogre::NameValuePairList &) */
        virtual void     restore(Ogre::NameValuePairList &retList);
        /** @copydoc CBaseEditor::getAABB() */
        virtual Ogre::AxisAlignedBox getAABB();
        /**
        * Fetches light type as a string
        * @return light type as a string
        */
        virtual Ogre::String	getLightTypeString();
        /** @copydoc CBaseEditor::getDerivedPosition() */
        virtual Ogre::Vector3	getDerivedPosition();
        /** @copydoc CBaseEditor::getDerivedOrientation() */
        virtual Ogre::Quaternion getDerivedOrientation();
        /** @copydoc CBaseEditor::setDerivedPosition(Ogre::Vector3) */
        virtual void			setDerivedPosition(Ogre::Vector3 val);

    protected:
        Ogre::Light      *m_Handle;             /** Actual light handle */
        Ogre::Vector3     m_Position;           /** Light position (wrapper) */
        Ogre::Quaternion  m_Orientation;        /** Light orientation (wrapper) */
        Ogre::Vector3     m_Direction;          /** Light direction (wrapper) */
        int               m_LightType;          /** Light type (wrapper) */
        Ogre::ColourValue m_Diffuse;            /** Light diffuse color (wrapper) */
        Ogre::ColourValue m_Specular;           /** Light specular color (wrapper) */
        Ogre::Vector3     m_Range;              /** Light range (wrapper) */
        Ogre::Vector4     m_Attenuation;        /** Light attenuation (wrapper) */
        Ogre::Real        m_Power;              /** Light power/intensity (wrapper) */
        bool              m_CastShadows;        /** Light shadow casting flag */
        
        /**
        * Constructor
        */
        CLightEditor();
        /**
        * Destructor
        */
        virtual           ~CLightEditor();

        /**
        * Calculates light current orientation
        */
        void              _calculateOrientation();
        /**
        * Converts light type string into Ogre::Light::LightTypes type
        * @param val light type string
        * @return light type
        */
        Ogre::Light::LightTypes _convertLightType(Ogre::String val);
    };

    //! Light editor factory class
    /*!  
        A class that instantiates light editor and tracks it thereafter
    */
    class OgitorExport CLightEditorFactory: public CBaseEditorFactory
    {
    public:
        /**
        * Constructor
        */
        CLightEditorFactory();
        /**
        * Destructor
        */
        virtual ~CLightEditorFactory() {};
        /** @copydoc CBaseEditorFactory::Init() */
        virtual void Init();
        /** @copydoc CBaseEditorFactory::CreateObject(CBaseEditor **, Ogre::NameValuePairList &) */
        virtual CBaseEditor *CreateObject(CBaseEditor **parent, Ogre::NameValuePairList &params);
        /** @copydoc CBaseEditorFactory::GetPlaceHolderName() */
        virtual Ogre::String GetPlaceHolderName() {return "scbLight_Omni.mesh";};
    };
}
